from QKDNetwork import QKDNetwork
from compare_noise import Compare
import concurrent.futures
import csv
import matplotlib.pyplot as plt
import numpy as np


# 第一张图：y轴 - 时隙数量, x轴 - 噪声均值
# 根据噪声变路由/定路由 的 T vs 噪声均值（两条线）

# 第二张图：y轴 - 时隙数量, x轴 - 阈值（超过阈值之后才变路由）
# 根据噪声变路由/定路由 的 T vs 阈值（两条线）


# Add:  监控网络中残余的密钥
#       监控某个SD对还没满足的密钥数量


default_avg_noise = 20
default_threshold_noise = 20
max_core_num = 96


def experiment(avg_noise, threshold_noise):
    # 节点个数： 60,  源目对数： 50,  阿尔法值： 0.2
    # avg_noise - 噪声的均值
    # threshold_noise - 噪声的阈值
    num_node = 60
    sd_num = 50
    alpha = 0.2
    q = QKDNetwork(
        showTopology=False, num_node=num_node, sd_num=sd_num, alpha=alpha, hete=True
    )
    c = Compare(q, avg_noise, threshold_noise)
    data = c.getData()
    return data


# 改变噪声的均值
def run_experiments_var_noise_avg():
    total_results = []
    for round_idx in range(20):
        round_results = []
        avg_noise = round_idx
        threshold_noise = default_threshold_noise
        with concurrent.futures.ThreadPoolExecutor(
            max_workers=max_core_num
        ) as executor:
            future_list = [
                executor.submit(experiment, avg_noise, threshold_noise)
                for _ in range(96)
            ]
            for future in concurrent.futures.as_completed(future_list):
                data = future.result()
                if data is not None and data[0] < 200 and data[1] < 200:
                    round_results.append(data)
                    print(f"avg_noise {avg_noise}: ", data)
                else:
                    break
        print(
            {
                "avg_noise": avg_noise,
                "threshold_noise": threshold_noise,
            }
        )
        print(np.mean(round_results, axis=0))
        if not round_results:
            break


# 改变噪声的阈值，超过一定的阈值之后才变路由
def run_experiments_var_noise_threshold():
    total_results = []
    for round_idx in range(50):
        round_results = []
        avg_noise = 10
        threshold_noise = round_idx
        with concurrent.futures.ThreadPoolExecutor(
            max_workers=max_core_num
        ) as executor:
            future_list = [
                executor.submit(experiment, avg_noise, threshold_noise)
                for _ in range(96)
            ]
            for future in concurrent.futures.as_completed(future_list):
                data = future.result()
                if data is not None and data[0] < 200 and data[1] < 200:
                    round_results.append(data)
                    print(f"threshold_noise {threshold_noise}: ", data)
                    # 将print语句替换为写入txt文件
                    with open("experiment_results.txt", "a") as f:
                        f.write(f"threshold_noise {threshold_noise}: {data}\n")
                else:
                    break
        if not round_results:
            break


def run_single_case():
    data = experiment(10, 3)
    # print(data)


def run_single_case_parallel():
    for noise_threshold in range(1, 20, 3):
        total_num = []
        with concurrent.futures.ThreadPoolExecutor(
            max_workers=max_core_num
        ) as executor:
            future_list = [
                executor.submit(experiment, 10, noise_threshold) for _ in range(96)
            ]
            for future in concurrent.futures.as_completed(future_list):
                data = future.result()
                total_num.append(data)
                print(data)
        # print("阈值为", noise_threshold)
        # print("结果为", np.mean(total_num, axis=0))


# run_single_case_parallel()
# run_single_case()

# run_experiments_var_noise_avg()
run_experiments_var_noise_threshold()
